/**
 * Copyright 2008 - 2009 Pro-Netics S.P.A.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package it.pronetics.madstore.hatom.alfresco.util;

import it.pronetics.madstore.hatom.alfresco.web.bean.HEntryBean;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import nu.xom.Attribute;
import nu.xom.Element;
import nu.xom.Node;
import nu.xom.Nodes;
import nu.xom.ParentNode;

/**
 * A class of useful methods made to manage some logical operation for this
 * plug-in.
 * 
 * @author Salvatore Incandela
 */

public class HAtomDialogUtils {

	public static final String HATOM_HENTRY = "hentry";
	public static final String HATOM_TITLE = "entry-title";
	public static final String HATOM_CONTENT = "entry-content";
	public static final String HATOM_UPDATED = "updated";
	public static final String HATOM_AUTHOR = "vcard author";
	public static final String HATOM_SUMMARY = "entry-summary";

	/**
	 * This method is used to perform the persistent removal of an hEntry
	 * 
	 * @param entryToDelete
	 *            HEntryBean representing the hEntry
	 * @param id2Elements
	 *            Map where are stored the references to the Node to Remove.
	 */

	public static void deleteHEntry(final HEntryBean entryToDelete,
			Map<String, Element> id2Elements) {
		List<Element> propertiesToDelete = getProperties(entryToDelete,
				id2Elements);
		XomUtils.deleteElements(propertiesToDelete);
		Element entry = id2Elements.remove(entryToDelete.getName());
		ParentNode entryParent = entry.getParent();
		Nodes children = entry.query("child::node()");
		for (int i = 0; i < children.size(); i++) {
			Node child = children.get(i);
			child.detach();
			entryParent.appendChild(child);
		}
		entryParent.removeChild(entry);
	}

	/**
	 * This method returns a list of Element that are the properties of the
	 * passedHEntry. Attention: the properties are removed from passed the map.
	 * 
	 * @param entry
	 *            Passed entry.
	 * @param id2Elements
	 *            Map where are stored the references to the real Nodes.
	 * @return List of Element, that are properties of the passed hEntry.
	 */

	public static List<Element> getProperties(final HEntryBean entry,
			Map<String, Element> id2Elements) {
		List<Element> propertiesToDelete = new ArrayList<Element>();
		Element title = id2Elements.remove(entry.getTitle());
		Element summary = id2Elements.remove(entry.getSummary());
		Element content = id2Elements.remove(entry.getContent());
		Element updated = id2Elements.remove(entry.getUpdated());
		Element author = id2Elements.remove(entry.getAuthor());
		propertiesToDelete.add(title);
		propertiesToDelete.add(summary);
		propertiesToDelete.add(content);
		propertiesToDelete.add(updated);
		propertiesToDelete.add(author);
		return propertiesToDelete;
	}

	public static void retrieveAndStoreHentry(Node node, HEntryBean entry,
			Map<String, Element> id2Elements) {
		if (node instanceof Element) {
			buildHEntryBean(node, entry, id2Elements);
		}
		for (int i = 0; i < node.getChildCount(); i++) {
			retrieveAndStoreHentry(node.getChild(i), entry, id2Elements);
		}
	}

	private static void buildHEntryBean(Node child, HEntryBean entry,
			Map<String, Element> id2Elements) {
		String valueClass;
		Element elementChild = (Element) child;
		valueClass = elementChild.getAttributeValue("class");
		if (valueClass != null
				&& valueClass.equals(HAtomDialogUtils.HATOM_TITLE)) {
			String valueSelect = SelectItemUtils.getValueSelect(elementChild);
			entry.setTitle(valueSelect);
			id2Elements.put(valueSelect, elementChild);
		} else if (valueClass != null
				&& valueClass.equals(HAtomDialogUtils.HATOM_AUTHOR)) {
			String valueSelect = SelectItemUtils.getValueSelect(elementChild);
			entry.setAuthor(valueSelect);
			id2Elements.put(valueSelect, elementChild);
		} else if (valueClass != null
				&& valueClass.equals(HAtomDialogUtils.HATOM_CONTENT)) {
			String valueSelect = SelectItemUtils.getValueSelect(elementChild);
			entry.setContent(valueSelect);
			id2Elements.put(valueSelect, elementChild);
		} else if (valueClass != null
				&& valueClass.equals(HAtomDialogUtils.HATOM_SUMMARY)) {
			String valueSelect = SelectItemUtils.getValueSelect(elementChild);
			entry.setSummary(valueSelect);
			id2Elements.put(valueSelect, elementChild);
		} else if (valueClass != null
				&& valueClass.equals(HAtomDialogUtils.HATOM_UPDATED)) {
			String valueSelect = SelectItemUtils.getValueSelect(elementChild);
			entry.setUpdated(valueSelect);
			id2Elements.put(valueSelect, elementChild);
		}
	}

	public static int occurInList(String property, List<String> listString) {
		int result = 0;
		for (String tomatch : listString) {
			if (property != null && tomatch != null && property.equals(tomatch)
					&& !property.equals(SelectItemUtils.NOT_SELECTED)) {
				result++;
			}
		}
		return result;
	}

	/**
	 * This method adds the hEntry Microformat for a defined hEntry described by
	 * its nodes.
	 * 
	 * @param nodes
	 *            List of the nodes describing the defined hEntry
	 */

	public static void addMicroformatsHEntry(List<Node> nodes) {
		Attribute classDef = new Attribute("class",
				HAtomDialogUtils.HATOM_HENTRY);
		Element hEntryElement = new Element(XomUtils.DIV);
		hEntryElement.addAttribute(classDef);
		if (nodes.size() > 1) {
			Element lowestCommonAncestor = (Element) XomUtils
					.getLowestCommonAncestor(nodes);
			Nodes oldNodes = lowestCommonAncestor.removeChildren();
			for (int i = 0; i < oldNodes.size(); i++) {
				hEntryElement.insertChild(oldNodes.get(i), i);
			}
			lowestCommonAncestor.appendChild(hEntryElement);
		} else if (nodes.size() == 1) {
			Node property = nodes.get(0);
			ParentNode parent = property.getParent();
			hEntryElement.appendChild(property.copy());
			parent.replaceChild(property, hEntryElement);
		}
	}

	/**
	 * This method adds the hAtom Microformat at one Node.
	 * 
	 * @param tagElementName
	 *            The name of the tag that is going to contain the hAtom class
	 *            definition.
	 * @param idString
	 *            Id of the node where to apply the hAtom Microformat
	 * @param classDef
	 *            The hAtom class definition to apply
	 * @param id2Elements
	 *            Map used to mapping elements starting from theri full
	 *            description
	 * @return Modified Element Node
	 */

	public static Element addMicroformatsHAtomToOneNode(String tagElementName,
			String idString, String classDef, Map<String, Element> id2Elements) {
		if (!idString.equals(SelectItemUtils.NOT_SELECTED)) {
			Element element = id2Elements.get(idString);
			Element newElement = new Element(tagElementName);
			Attribute hAtomAttribute = new Attribute("class", classDef);
			newElement.addAttribute(hAtomAttribute);
			newElement.appendChild(new Element(element));
			element.getParent().replaceChild(element, newElement);
			return newElement;
		} else
			return null;
	}

}
